import { SSHResultType } from '../types'

export const SSHTimeoutMiddleware_Name = 'SSHTimeoutMiddleware'
export const SSHTimeoutMiddlewareType_Name = 'SSHTimeoutMiddlewareType'

/**
 * SSH 超时处理中间件
 *
 * @param fun 处理函数
 * @param options 配置选项
 * - timeout 超时时间，单位为 ms，默认 5000ms
 * - thisArg 指定处理函数的 this 指向，默认为 null，即非严格模式下函数调用时的 this 指向全
 * 局对象，严格模式下为 thisArg 指定的值；对于需要节流处理的函数为箭头函数时，该参数无效，箭头
 * 函数的 this 指向由函数定义时确定，不受 thisArg 参数影响，箭头函数的 this 来源于箭头函数定
 * 义时的上级作用域。
 * @returns 返回值 增加了超时处理后的处理函数
 */
export const SSHTimeoutMiddleware = (
  fun: (...args: any[]) => Promise<SSHResultType>,
  options: {
    timeout?: number
    thisArg?: any
  } = {}
): ((...args: any[]) => Promise<SSHResultType>) => {
  const { timeout, thisArg } = {
    timeout: 5000,
    thisArg: null,
    ...options
  }
  return async (...args: any[]): Promise<SSHResultType> => {
    let timer: NodeJS.Timeout | null = null
    try {
      // 设置超时
      const timerPromise = new Promise<never>((_, reject) => {
        timer = setTimeout(() => {
          reject(new Error(`Connection timed out after ${timeout}ms`))
        }, timeout)
      })
      // 执行处理函数
      return await Promise.race([fun.apply(thisArg, args), timerPromise])
    } catch (error) {
      return Promise.reject(error)
    } finally {
      // 清除超时计时器
      if (timer) clearTimeout(timer)
    }
  }
}

export type SSHTimeoutMiddlewareType = typeof SSHTimeoutMiddleware
